﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DocumentFormat.OpenXml.Lite.Shared
{
    public class EventList<T> : List<T>
    {
        public event ListEventHandler<T> Changing;

        public new T this[int index] 
        {
            get { return base[index]; }
            set
            {
                if (Changing != null)
                {
                    ListEventArgs<T> args = new ListEventArgs<T>(value, ListEventType.Add);
                    Changing(this, args);
                    if (args.Canceled)
                    {
                        return;
                    }
                }
                base[index] = value;
            }
        }

        public new void Add(T item)
        {
            if (Changing != null)
            {
                ListEventArgs<T> args = new ListEventArgs<T>(item, ListEventType.Add);
                Changing(this, args);
                if (args.Canceled)
                {
                    return;
                }
            }
            base.Add(item);
        }

        public new void AddRange(IEnumerable<T> collection)
        {
            if (Changing != null)
            {
                ListEventArgs<T> args = new ListEventArgs<T>(collection, ListEventType.Add);
                Changing(this, args);
                if (args.Canceled)
                {
                    return;
                }
            }
            base.AddRange(collection);
        }

        public new void Insert(int index, T item)
        {
            if (Changing != null)
            {
                ListEventArgs<T> args = new ListEventArgs<T>(item, ListEventType.Insert);
                Changing(this, args);
                if (args.Canceled)
                {
                    return;
                }
            }
            base.Insert(index, item);
        }

        public new void InsertRange(int index, IEnumerable<T> collection)
        {
            if (Changing != null)
            {
                ListEventArgs<T> args = new ListEventArgs<T>(collection, ListEventType.Insert);
                Changing(this, args);
                if (args.Canceled)
                {
                    return;
                }
            }
            base.InsertRange(index, collection);
        }

        public new bool Remove(T item)
        {
            if (Changing != null)
            {
                ListEventArgs<T> args = new ListEventArgs<T>(item, ListEventType.Remove);
                Changing(this, args);
                if (args.Canceled)
                {
                    return false;
                }
            }
            return base.Remove(item);
        }

        public new int RemoveAll(Predicate<T> match)
        {
            if (Changing != null)
            {
                List<T> matches = new List<T>();
                foreach (var e in this)
                {
                    if (match.Invoke(e))
                    {
                        matches.Add(e);
                    }
                }

                ListEventArgs<T> args = new ListEventArgs<T>(matches, ListEventType.Remove);
                Changing(this, args);
                if (args.Canceled)
                {
                    return 0;
                }
                Changing(this, args);
                if (args.Canceled)
                {
                    return 0;
                }
            }
            return base.RemoveAll(match);
        }

        public new void RemoveAt(int index)
        {
            if (Changing != null)
            {
                ListEventArgs<T> args = new ListEventArgs<T>(this[index], ListEventType.Remove);
                Changing(this, args);
                if (args.Canceled)
                {
                    return;
                }
            }
            base.RemoveAt(index);
        }

        public new void RemoveRange(int index, int count)
        {
            if (Changing != null)
            {
                ListEventArgs<T> args = new ListEventArgs<T>(this.GetRange(index, count), ListEventType.Remove);
                Changing(this, args);
                if (args.Canceled)
                {
                    return;
                }
            }
            base.RemoveRange(index, count);
        }
    }
}
